import tkinter as tk
import random
import copy

class Game2048:
    def __init__(self, master):
        self.master = master
        self.master.title("2048游戏")
        self.master.resizable(False, False)
        self.master.geometry("400x500")
        self.master.bind("<Key>", self.key_press)
        
        # 游戏设置
        self.grid_size = 4
        self.cell_size = 80
        self.grid_padding = 10
        
        # 游戏状态
        self.grid = [[0 for _ in range(self.grid_size)] for _ in range(self.grid_size)]
        self.score = 0
        self.history = []
        self.game_over = False
        self.you_win = False
        
        # 颜色配置
        self.bg_color = "#faf8ef"
        self.cell_colors = {
            0: "#cdc1b4",
            2: "#eee4da",
            4: "#ede0c8",
            8: "#f2b179",
            16: "#f59563",
            32: "#f67c5f",
            64: "#f65e3b",
            128: "#edcf72",
            256: "#edcc61",
            512: "#edc850",
            1024: "#edc53f",
            2048: "#edc22e",
            4096: "#3c3a32",
            8192: "#3c3a32"
        }
        self.text_colors = {
            0: "#cdc1b4",
            2: "#776e65",
            4: "#776e65",
            8: "#f9f6f2",
            16: "#f9f6f2",
            32: "#f9f6f2",
            64: "#f9f6f2",
            128: "#f9f6f2",
            256: "#f9f6f2",
            512: "#f9f6f2",
            1024: "#f9f6f2",
            2048: "#f9f6f2",
            4096: "#f9f6f2",
            8192: "#f9f6f2"
        }
        
        # 创建UI
        self.create_ui()
        
        # 初始化游戏
        self.start_new_game()
    
    def create_ui(self):
        # 创建主框架
        self.main_frame = tk.Frame(self.master, bg=self.bg_color)
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题和分数
        title_frame = tk.Frame(self.main_frame, bg=self.bg_color)
        title_frame.pack(fill=tk.X, padx=self.grid_padding, pady=self.grid_padding)
        
        title_label = tk.Label(title_frame, text="2048", font=("Arial", 40, "bold"), bg=self.bg_color, fg="#776e65")
        title_label.pack(side=tk.LEFT)
        
        score_frame = tk.Frame(title_frame, bg="#bbada0", padx=10, pady=5)
        score_frame.pack(side=tk.RIGHT)
        
        tk.Label(score_frame, text="分数", font=("Arial", 12), bg="#bbada0", fg="#eee4da").pack()
        self.score_label = tk.Label(score_frame, text="0", font=("Arial", 18, "bold"), bg="#bbada0", fg="white")
        self.score_label.pack()
        
        # 游戏说明
        desc_frame = tk.Frame(self.main_frame, bg=self.bg_color)
        desc_frame.pack(fill=tk.X, padx=self.grid_padding, pady=(0, self.grid_padding))
        
        tk.Label(desc_frame, text="使用方向键移动数字。相同数字相撞时会合并！", 
                 font=("Arial", 12), bg=self.bg_color, fg="#776e65").pack(side=tk.LEFT)
        
        # 重新开始按钮
        restart_button = tk.Button(desc_frame, text="重新开始", font=("Arial", 12, "bold"), 
                                  bg="#8f7a66", fg="white", command=self.start_new_game)
        restart_button.pack(side=tk.RIGHT)
        
        # 创建游戏网格
        self.grid_frame = tk.Frame(self.main_frame, bg="#bbada0", padx=self.grid_padding, pady=self.grid_padding)
        self.grid_frame.pack(fill=tk.BOTH, expand=True, padx=self.grid_padding, pady=self.grid_padding)
        
        self.cell_frames = []
        self.cell_labels = []
        
        for i in range(self.grid_size):
            row_frames = []
            row_labels = []
            for j in range(self.grid_size):
                cell_frame = tk.Frame(self.grid_frame, bg=self.cell_colors[0], 
                                     width=self.cell_size, height=self.cell_size)
                cell_frame.grid(row=i, column=j, padx=5, pady=5)
                cell_frame.grid_propagate(False)
                
                cell_label = tk.Label(cell_frame, text="", font=("Arial", 20, "bold"), 
                                     bg=self.cell_colors[0], fg=self.text_colors[0])
                cell_label.place(relx=0.5, rely=0.5, anchor="center")
                
                row_frames.append(cell_frame)
                row_labels.append(cell_label)
            
            self.cell_frames.append(row_frames)
            self.cell_labels.append(row_labels)
    
    def start_new_game(self):
        # 重置游戏状态
        self.grid = [[0 for _ in range(self.grid_size)] for _ in range(self.grid_size)]
        self.score = 0
        self.history = []
        self.game_over = False
        self.you_win = False
        
        # 更新分数显示
        self.score_label.config(text=str(self.score))
        
        # 生成两个初始数字
        self.generate_new_number()
        self.generate_new_number()
        
        # 更新显示
        self.update_grid_display()
    
    def generate_new_number(self):
        # 查找所有空白位置
        empty_cells = []
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                if self.grid[i][j] == 0:
                    empty_cells.append((i, j))
        
        if empty_cells:
            # 随机选择一个空白位置
            i, j = random.choice(empty_cells)
            # 90%概率生成2，10%概率生成4
            self.grid[i][j] = 2 if random.random() < 0.9 else 4
    
    def update_grid_display(self):
        # 更新每个单元格的显示
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                value = self.grid[i][j]
                self.cell_frames[i][j].config(bg=self.cell_colors.get(value, "#3c3a32"))
                self.cell_labels[i][j].config(
                    text="" if value == 0 else str(value),
                    bg=self.cell_colors.get(value, "#3c3a32"),
                    fg=self.text_colors.get(value, "white")
                )
                
                # 根据数字大小调整字体
                if value < 100:
                    self.cell_labels[i][j].config(font=("Arial", 24, "bold"))
                elif value < 1000:
                    self.cell_labels[i][j].config(font=("Arial", 20, "bold"))
                else:
                    self.cell_labels[i][j].config(font=("Arial", 16, "bold"))
        
        # 检查游戏状态
        if self.you_win:
            self.show_message("恭喜你赢了！")
        elif self.game_over:
            self.show_message("游戏结束！")
    
    def show_message(self, message):
        # 创建半透明覆盖层
        overlay = tk.Frame(self.grid_frame, bg="black", alpha=0.5)
        overlay.place(relx=0, rely=0, relwidth=1, relheight=1)
        
        # 创建消息框
        message_frame = tk.Frame(self.grid_frame, bg="#faf8ef", padx=20, pady=20)
        message_frame.place(relx=0.5, rely=0.5, anchor="center")
        
        tk.Label(message_frame, text=message, font=("Arial", 20, "bold"), 
                bg="#faf8ef", fg="#776e65").pack(pady=10)
        
        # 继续游戏按钮
        if self.you_win:
            continue_button = tk.Button(message_frame, text="继续游戏", 
                                      font=("Arial", 12, "bold"), bg="#8f7a66", 
                                      fg="white", command=lambda: overlay.destroy())
            continue_button.pack(pady=5)
    
    def key_press(self, event):
        if self.game_over or (self.you_win and not event.keysym.startswith('Continue')):
            return
        
        # 保存当前状态用于撤销
        self.history.append((copy.deepcopy(self.grid), self.score))
        if len(self.history) > 10:  # 只保留最近10步
            self.history.pop(0)
        
        moved = False
        
        if event.keysym == 'Up':
            moved = self.move_up()
        elif event.keysym == 'Down':
            moved = self.move_down()
        elif event.keysym == 'Left':
            moved = self.move_left()
        elif event.keysym == 'Right':
            moved = self.move_right()
        elif event.keysym == 'u' and len(self.history) > 0:  # 撤销功能
            self.grid, self.score = self.history.pop()
            self.score_label.config(text=str(self.score))
            self.update_grid_display()
            return
        
        if moved:
            self.generate_new_number()
            self.update_grid_display()
            self.check_game_state()
    
    def move_up(self):
        moved = False
        for j in range(self.grid_size):
            # 合并相同数字
            for i in range(1, self.grid_size):
                if self.grid[i][j] != 0:
                    row = i
                    while row > 0 and self.grid[row-1][j] == 0:
                        self.grid[row-1][j] = self.grid[row][j]
                        self.grid[row][j] = 0
                        row -= 1
                        moved = True
                    
                    if row > 0 and self.grid[row-1][j] == self.grid[row][j]:
                        self.grid[row-1][j] *= 2
                        self.score += self.grid[row-1][j]
                        self.grid[row][j] = 0
                        moved = True
        
        self.score_label.config(text=str(self.score))
        return moved
    
    def move_down(self):
        moved = False
        for j in range(self.grid_size):
            # 合并相同数字
            for i in range(self.grid_size-2, -1, -1):
                if self.grid[i][j] != 0:
                    row = i
                    while row < self.grid_size-1 and self.grid[row+1][j] == 0:
                        self.grid[row+1][j] = self.grid[row][j]
                        self.grid[row][j] = 0
                        row += 1
                        moved = True
                    
                    if row < self.grid_size-1 and self.grid[row+1][j] == self.grid[row][j]:
                        self.grid[row+1][j] *= 2
                        self.score += self.grid[row+1][j]
                        self.grid[row][j] = 0
                        moved = True
        
        self.score_label.config(text=str(self.score))
        return moved
    
    def move_left(self):
        moved = False
        for i in range(self.grid_size):
            # 合并相同数字
            for j in range(1, self.grid_size):
                if self.grid[i][j] != 0:
                    col = j
                    while col > 0 and self.grid[i][col-1] == 0:
                        self.grid[i][col-1] = self.grid[i][col]
                        self.grid[i][col] = 0
                        col -= 1
                        moved = True
                    
                    if col > 0 and self.grid[i][col-1] == self.grid[i][col]:
                        self.grid[i][col-1] *= 2
                        self.score += self.grid[i][col-1]
                        self.grid[i][col] = 0
                        moved = True
        
        self.score_label.config(text=str(self.score))
        return moved
    
    def move_right(self):
        moved = False
        for i in range(self.grid_size):
            # 合并相同数字
            for j in range(self.grid_size-2, -1, -1):
                if self.grid[i][j] != 0:
                    col = j
                    while col < self.grid_size-1 and self.grid[i][col+1] == 0:
                        self.grid[i][col+1] = self.grid[i][col]
                        self.grid[i][col] = 0
                        col += 1
                        moved = True
                    
                    if col < self.grid_size-1 and self.grid[i][col+1] == self.grid[i][col]:
                        self.grid[i][col+1] *= 2
                        self.score += self.grid[i][col+1]
                        self.grid[i][col] = 0
                        moved = True
        
        self.score_label.config(text=str(self.score))
        return moved
    
    def check_game_state(self):
        # 检查是否获胜
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                if self.grid[i][j] >= 2048:
                    self.you_win = True
                    return
        
        # 检查是否还有空格
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                if self.grid[i][j] == 0:
                    return
        
        # 检查是否还能移动
        for i in range(self.grid_size):
            for j in range(self.grid_size-1):
                if self.grid[i][j] == self.grid[i][j+1]:
                    return
        
        for j in range(self.grid_size):
            for i in range(self.grid_size-1):
                if self.grid[i][j] == self.grid[i+1][j]:
                    return
        
        # 如果都不满足，游戏结束
        self.game_over = True

if __name__ == "__main__":
    root = tk.Tk()
    game = Game2048(root)
    root.mainloop()